﻿using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml.Linq;
using ForceSystem.Untangler;
using ForceSystem.Untangler.View;
using System.Collections.Generic;
using Microsoft.Win32;

namespace UntanglerApp
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1
    {
        public Window1()
        {
            InitializeComponent();

            LoadAssemblyPacks();
        }

        void LoadAssemblyPacks()
        {
            const string assemblyPackFilename = "AssemblyPacks.xml";
            if (!File.Exists(assemblyPackFilename))
            {
                return;
            }

            var xElement = XDocument.Load(assemblyPackFilename).Element("AssemblyPacks");
            if (xElement != null)
            {
                assemblyPacksMenu.IsEnabled = true;
                _assemblyPacks = (from e in xElement.Elements("AssemblyPack")
                                  select AssemblyPack.FromXElement(e)).ToDictionary(p => p.Name);

                var names = from name in _assemblyPacks.Keys
                            orderby name
                            select name;
                foreach (var name in names)
                {
                    var pack = _assemblyPacks[name];
                    var root = Utils.EvaluateEnvironmentVariables(pack.Root);
                    var filenames = (from filename in pack.Assemblies
                                    select Path.Combine(root, Utils.EvaluateEnvironmentVariables(filename))).ToArray();

                    var menuItem = new MenuItem
                    {
                        Header = name,
                        Tag = filenames,
                    };

                    if ((from a in filenames where !File.Exists(a) select a).Any())
                    {
                        // Some of files are not exists, disable menu item.
                        menuItem.IsEnabled = false;
                    }

                    menuItem.Click += (sender, args) => LoadAssemblies(((MenuItem)sender).Tag as string[]);
                    assemblyPacksMenu.Items.Add(menuItem);
                }
            }

        }

        void LoadAssemblies(IEnumerable<string> assemblyFilenames)
        {
            _context = new UntangledContext();
            treeView1.Items.Clear();

            try
            {
                foreach (var filename in assemblyFilenames)
                {
                    _context.AddAssembly(filename);
                }

                foreach (var ns in _context.Namespaces)
                {
                    var nsItem = new TreeViewItem { Header = ns.Name };
                    foreach (var type in ns.Types)
                    {
                        var item = new TreeViewItem { Tag = type, Header = type.DisplayName };
                        nsItem.Items.Add(item);
                    }
                    treeView1.Items.Add(nsItem);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(String.Format("Can't load assemblies.\r\n\r\nException Message:\r\n{0}", e.Message));
                _context = null;
                treeView1.Items.Clear();
            }
        }

        private void CommandBindingOpenExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var dialog = new OpenFileDialog
                             {
                                 Filter = "DLL files (*.dll)|*.dll|All files (*.*)|*.*",
                                 FilterIndex = 1,
                                 RestoreDirectory = true
                             };

            if(dialog.ShowDialog().Value)
            {
                LoadAssemblies(dialog.FileNames);
            }
        }

        private void CommandBindingSaveExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (_canvas == null)
            {
                return;
            }

            var encoder = new PngBitmapEncoder();
            var visual = _canvas;
            var bitmap = new RenderTargetBitmap((int)visual.Width, (int)visual.Height, 96, 96, PixelFormats.Pbgra32);
            bitmap.Render(visual);
            var frame = BitmapFrame.Create(bitmap);
            encoder.Frames.Add(frame);

            var filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
                String.Format("Untangler-{0}.png", DateTime.Now.ToString("yyyy-MM-dd_hh-mm-ss")));

            using (var stream = File.Create(filename))
            {
                encoder.Save(stream);
            }

            var runExplorer = new System.Diagnostics.ProcessStartInfo {FileName = "explorer.exe", Arguments = filename};
            System.Diagnostics.Process.Start(runExplorer); 
        }

        private void TreeView1SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {

            var item = treeView1.SelectedItem as TreeViewItem;

            if (item != null && item.Tag != null)
            {
                viewGrid.Children.Clear();
                _canvas = ViewHelper.GenrateDrivedView(viewGrid, item.Tag as UntangledType);
            }
        }

        private UntangledContext _context = new UntangledContext();
        private FrameworkElement _canvas;
        private Dictionary<string, AssemblyPack> _assemblyPacks;

        private void WindowFileDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                LoadAssemblies((string[]) e.Data.GetData(DataFormats.FileDrop));
            }
        }

    }
}
